#include <windows.h>
#include <queue.h>
#include <cqueue.h>
#include <sqstack.h>
#include <cstdio>


void setup() {
    // 设置控制台代码页为UTF-8
    SetConsoleOutputCP(CP_UTF8);
    // 设置控制台输入代码页为UTF-8
    SetConsoleCP(CP_UTF8);
    setvbuf(stdout, NULL, _IONBF, 0); // 设置为无缓冲模式
}


int main_LinkQueue() {
    LinkQueue Q;
    printf("输入你要入栈的元素，用空格分隔：");

    LinkQueue_Init(Q);

    char c;
    QElemType temp = 0;
    while ((c = getchar()) != '\n') {
        if (c != ' ') {
            temp = temp * 10 + (c - '0');
        } else {
            LinkQueue_En(Q, temp);
            temp = 0;
        }
    }

    // 最后一个元素入队
    LinkQueue_En(Q, temp);

    printf("目前队列：");
    LinkQueue_Display(Q);
    printf("\n");

    while (!LinkQueue_Empty(Q)) {
        QElemType e;
        LinkQueue_De(Q, e);
        printf("元素 %d 出队\n", e);
    }

    return 0;
}


int main_CQueue() {
    CQLink Q;
    printf("输入你要入栈的元素，用空格分隔：");

    CQueue_Init(Q);

    char c;
    QElemType temp = 0;
    while ((c = getchar()) != '\n') {
        if (c != ' ') {
            temp = temp * 10 + (c - '0');
        } else {
            CQueue_In(Q, temp);
            temp = 0;
        }
    }

    // 最后一个元素入队
    CQueue_In(Q, temp);

    printf("目前队列：");
    CQueue_Display(Q);
    printf("\n");

    QElemType e;
    while (CQueue_Out(Q, e) == OK) {
        printf("元素 %d 出队\n", e);
    }

    return 0;
}

int main_doctor() {
    LinkQueue Q;
    LinkQueue_Init(Q);

    printf("==================================\n");
    printf("1:排队   2:就诊   3:查看排队   4:下班\n");
    printf("==================================\n");

    int finish = 1;
    while (finish) {
        printf("输入功能序号：");

        int id;
        int user;
        scanf("%d", &user);

        switch (user) {
            case 1: {
                printf("请输入病历号：");
                scanf("%d", &id);

                QueuePtr p = Q.front->next;
                while (p != NULL) {
                    if (p->data == id) {
                        break;
                    }
                    p = p->next;
                }

                if (p != NULL) {
                    printf("病历号重复，请重新输入。\n");
                    break;
                }

                LinkQueue_En(Q, id);
                break;
            }
            case 2:
                if (LinkQueue_De(Q, id) == OK) {
                    printf("%d 前往就诊。\n", id);
                } else {
                    printf("目前没有排队的人。\n");
                }
                break;
            case 3:
                printf("目前排队队伍：");
                LinkQueue_Display(Q);
                printf("\n");
                break;
            case 4:
                finish = 0;
                if (!LinkQueue_Empty(Q)) printf("以下病人下午就诊：");
                while (!LinkQueue_Empty(Q)) {
                    QElemType e;
                    LinkQueue_De(Q, e);
                    printf("%d ", e);
                }
                break;
            default:
                printf("输入错误，请重新输入。\n");
                break;
        }
    }
}

int main_cat() {

    /*
    * 请输入发牌数：6
    * 玩家甲：2 4 1 2 5 6
    * 玩家乙：3 1 3 5 6 4
    */

    int times = 0;
    LinkQueue Q1;
    LinkQueue Q2;
    SqStack S;

    LinkQueue_Init(Q1);
    LinkQueue_Init(Q2);
    SqStack_Init(S);

    printf("请输入发牌数：");
    scanf("%d", &times);

    printf("玩家甲：");

    for (int i = 0; i < times; i++) {
        int temp;
        // if (temp > 9 || temp < 0) {
        //     printf("输入错误。");
        //     return ERROR;
        // }
        scanf("%d", &temp);
        LinkQueue_En(Q1, temp);
    }


    printf("玩家乙：");

    for (int i = 0; i < times; i++) {
        int temp;
        // if (temp > 9 || temp < 0) {
        //     printf("输入错误。");
        //     return ERROR;
        // }
        scanf("%d", &temp);
        LinkQueue_En(Q2, temp);
    }

    // 模拟进行游戏
    int turning = 0; // 谁拿牌
    int bucket[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    while (!(LinkQueue_Empty(Q1) || LinkQueue_Empty(Q2))) {

        int card;
        if (turning == 0) {
            LinkQueue_De(Q1, card);
            SqStack_Push(S, card);

            // 判断是否有重复
            if (bucket[card] == 1) {
                int temp_card; // 从桌子上拿回来的卡片

                SqStack_Pop(S, temp_card);
                LinkQueue_En(Q1, temp_card);

                do {
                    SqStack_Pop(S, temp_card);
                    bucket[temp_card] = 0;
                    LinkQueue_En(Q1, temp_card);
                } while (temp_card != card);

                bucket[card] = 0;
            } else {
                bucket[card] = 1;
            }

            turning = 1;
        } else {
            LinkQueue_De(Q2, card);
            SqStack_Push(S, card);

            // 判断是否有重复
            if (bucket[card] == 1) {
                int temp_card; // 从桌子上拿回来的卡片

                SqStack_Pop(S, temp_card);
                LinkQueue_En(Q2, temp_card);

                do {
                    SqStack_Pop(S, temp_card);
                    bucket[temp_card] = 0;
                    LinkQueue_En(Q2, temp_card);
                } while (temp_card != card);

                bucket[card] = 0;
            } else {
                bucket[card] = 1;
            }

            turning = 0;
        }
    }

    QElemType temp;

    if (LinkQueue_Empty(Q1)) {
        printf("游戏结束：玩家乙获胜。\n手中的牌有：");

        // 收光了打一张
        LinkQueue_De(Q2, temp);
        SqStack_Push(S, temp);

        LinkQueue_Display(Q2);
        printf("\n");
    } else {
        printf("游戏结束：玩家甲获胜。\n手中的牌有：");

        // 收光了打一张
        LinkQueue_De(Q1, temp);
        SqStack_Push(S, temp);

        LinkQueue_Display(Q1);
        printf("\n");
    }

    printf("桌上的牌有：");
    SqStack_Display(S);

    return 0;
}


int main() {
    setup();

    printf("============================\n");
    printf("1:LinkQueue 2:门诊 3:小猫钓鱼\n");
    printf("============================\n");
    printf("输入需要测试的功能：");

    int user;
    scanf("%d", &user);

    if (user == 1) {
        main_LinkQueue();
    } else if (user == 2) {
        main_doctor();
    } else {
        main_cat();
    }

    return 0;
}